package com.hj.springframework2.io;

import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.*;
import java.util.*;
import java.util.function.Function;

/**
 * @Author : hujing
 * @Date: 2025/6/13 9:05
 * @Description:属性解析器
 */
public class PropertyResolver {
    final Logger logger = LoggerFactory.getLogger(getClass());

    Map<String, String> properties = new HashMap<>();
    Map<Class<?>, Function<String, Object>> converters = new HashMap<>();

    public PropertyResolver(Properties props) {
        //将操作系统的所有环境变量加载到properties中
        this.properties.putAll(System.getenv());
        //获取props中的属性名称
        Set<String> names = props.stringPropertyNames();
        for (String name : names) {
            this.properties.put(name, props.getProperty(name));
        }

        //定义默认的转换器
        converters.put(String.class, s -> s);

        converters.put(boolean.class, Boolean::parseBoolean);
        converters.put(Boolean.class, Boolean::parseBoolean);

        converters.put(byte.class, Byte::parseByte);
        converters.put(Byte.class, Byte::parseByte);

        converters.put(short.class, Short::parseShort);
        converters.put(Short.class, Short::parseShort);

        converters.put(int.class, Integer::parseInt);
        converters.put(Integer.class, Integer::parseInt);

        converters.put(long.class, Long::parseLong);
        converters.put(Long.class, Long::parseLong);

        converters.put(float.class, Float::parseFloat);
        converters.put(Float.class, Float::parseFloat);

        converters.put(double.class, Double::parseDouble);
        converters.put(Double.class, Double::parseDouble);

        converters.put(LocalDate.class, s -> LocalDate.parse(s));
        converters.put(LocalTime.class, s -> LocalTime.parse(s));
        converters.put(LocalDateTime.class, s -> LocalDateTime.parse(s));
        converters.put(ZonedDateTime.class, s -> ZonedDateTime.parse(s));
        converters.put(Duration.class, s -> Duration.parse(s));
        converters.put(ZoneId.class, s -> ZoneId.of(s));
    }

    public boolean containsProperty(String key) {
        return properties.containsKey(key);
    }

    /**
     * 根据属性表达式获取属性值
     *
     * @param key
     * @return
     */
    public String getProperty(String key) {
        PropertyExpr keyExpr = parsePropertyExpr(key);
        if (keyExpr != null) {
            if (keyExpr.getDefaultValue() != null) {
                //有默认值,按默认值去获取属性值
                return getProperty(keyExpr.getKey(), keyExpr.getDefaultValue());
            } else {
                return getProperty(keyExpr.getKey());
            }
        }
        // 普通key查询:
        String value = properties.get(key);
        if (value != null) {
            return parseValue(value);
        }
        return value;
    }

    /**
     * 根据属性表达式获取属性值,并转换成指定类型
     *
     * @param key
     * @param targetType
     * @param <T>
     * @return
     */
    public <T> T getProperty(String key, Class<T> targetType) {
        String value = getProperty(key);
        if (value == null) {
            return null;
        }
        return convert(targetType, value);
    }
    
    public <T> T getProperty(String key,Class<T> targetType,T defaultValue){
        String value = getProperty(key);
        if (value==null){
            return defaultValue;
        }
        return convert(targetType,value);
    }

    <T> T convert(Class<T> targetType, String value) {
        Function<String, Object> function = converters.get(targetType);
        if (function == null) {
            throw new IllegalArgumentException("Unsupported targetType: " + targetType.getName());
        }
        return (T) function.apply(value);
    }

    public String getProperty(String key, String defaultValue) {
        String value = getProperty(key);
        return value == null ? parseValue(defaultValue) : value;
    }

    String parseValue(String value) {
        PropertyExpr expr = parsePropertyExpr(value);
        if (expr == null) {
            return value;
        }
        if (expr.getDefaultValue() != null) {
            return getProperty(expr.getKey(), expr.getDefaultValue());
        } else {
            return getProperty(expr.getKey());
        }
    }

    /**
     * 解析属性表达式 ${abc.xyz:defaultValue}
     *
     * @param key
     * @return
     */
    private PropertyExpr parsePropertyExpr(String key) {
        if (key.startsWith("${") && key.endsWith("}")) {
            int colonIndex = key.indexOf(":");
            if (colonIndex == -1) {
                //没有默认值
                String k = key.substring(2, key.length() - 1);
                return new PropertyExpr(k, null);
            } else {
                //有默认值
                String k = key.substring(2, colonIndex);
                String defaultValue = key.substring(colonIndex + 1, key.length() - 1);
                return new PropertyExpr(k, defaultValue);
            }
        }
        return null;
    }

    public <T> T getRequiredProperty(String key, Class<T> targetType) {
        T value = getProperty(key, targetType);
        return Objects.requireNonNull(value,"Property '" + key + "' not found.");
    }
    
}

@Data
class PropertyExpr {
    String key;
    String defaultValue;

    public PropertyExpr(String key, String defaultValue) {
        this.key = key;
        this.defaultValue = defaultValue;
    }
}
